package com.congee02.deadlock;

import com.congee02.ThreadProvider;

/**
 * @author congee02
 * @date 2/2/2023 4:01 PM
 */
public class DeadLockTest {
    
    private static Object resourceA = new Object() {
        @Override
        public String toString() {
            return "resourceA";
        }
    };
    private static Object resourceB = new Object() {
        @Override
        public String toString() {
            return "resourceB";
        }
    };

    public static void main(String[] args) {
        new UsingResourceThread(resourceA, resourceB).thread().start();
        new UsingResourceThread(resourceB, resourceA).thread().start();
    }
    
    private static class UsingResourceThread implements ThreadProvider {
        
        private final Object beforeResource;
        private final Object afterResource;

        private UsingResourceThread(Object beforeResource, Object afterResource) {
            this.beforeResource = beforeResource;
            this.afterResource = afterResource;
        }

        @Override
        public void run() {
            String name = Thread.currentThread().getName();
            
            // 若线程 A 拿到 beforeResource 后，一直拿不到 afterResource，A 会一直占有 beforeResource
            // 此时，若线程 B 想拿到 beforeResource，则一直不会取到 (一直被线程 A 占有)
            // 这样的逻辑，很容易造成死锁
            synchronized (beforeResource) {
                System.out.println("[INFO]" + name + " get " + beforeResource);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("[INFO]" + name + " is trying to get " + afterResource);
                synchronized (afterResource) {
                    System.out.println("[INFO]" + name + " get " + afterResource);
                }
                System.out.println("[INFO]" + name + " has done");
            }
            
        }
    }
}
